package com.easypay;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.easypay.bean.ledger.*;
import com.easypay.util.AesUtil;
import com.easypay.util.HttpConnectUtils;
import com.easypay.util.RandomUtil;
import com.easypay.util.StringUtils;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 分账类及退款类交易
 *
 * @date: 2021/10/23 14:05
 * @author: pandans
 * https://doc.eycard.cn/web/#/23?page_id=4817
 */
public class Ledger extends BasePay{

    public static void main(String[] args) {

        // 退款
//        doMposRefund();

        // 退款查询
        //doMposFindRefund();

        //关闭jsapi订单
//        doCloseTrade();

        // 急速退货-账户代扣
//        doAccRefund();



        // 获取银联userid
//         String authCode = doYsfQrAuth();
        // doQrGetUserId(authCode);

        // 绑定分账 关系
//        doLedgerMposBind();

        // 分账关系 查询
//        doLedgerMposFindBind();

        // 请求分账
        doLedgerMpos();

        // 分账请求撤销
        //doLedgerMposCancel();

        // 退款

//        doMposRefund();
    }

    /*****************************************分账相关接口！！！分账的URL与之前不同******************************/

    /**
     * @Description 用于绑定分账方与分账接收方之间的分账关系, 1、分账交易的子商户（接收分账方）必须在分账请求之前，和交易商户绑定分账关系后才能分账
     * @date: 2021/10/17 22:11
     * @author: pandans
     */
    public static void doLedgerMposBind() {
        MposBind request = new MposBind();
        request.setOrgId(ORGID);
        request.setOrgMerCode(ORGMERCODE);
        request.setOrgTermNo(ORGTERMNO);
        request.setSignType(SIGN_TYPE_RSA);
        //业务产品码
        //request.setProdCode("");

        // 交易流水，28位定长，规则：orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度（唯一）
        request.setOrgTrace(ORGID.substring(0, 4) + ORGID.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));

        MposBind.BizDataBean dataBean = new MposBind.BizDataBean();
        // 分账接收方商户号
        String subOrgMer = ORGLedgerMERCODE;
        dataBean.setOrgMercode(subOrgMer);
        String subOrgTer = ORGLedgerTERMNO;
        dataBean.setOrgTermno(subOrgTer);

        request.setBizData(dataBean);

        // 使用商户私钥对data字段加签
        String sign = sign(dataBean, TEST_MER_RSA_PRIVATE_KEY);
        request.setSign(sign);

        String requestStr = JSON.toJSONString(request);

        try {
            String response = HttpConnectUtils.sendHttpSRequest(BASE_URL_LEDGER + "/ledger/mposbind", requestStr, "JSON", null);
            System.out.println("响应报文：" + response);
            checkSign(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 用于查询交易商户与分账接收方的绑定关系。
     * 1、需上送交易商户号与分账接收方信息，查询两者绑定关系
     * 2、单笔查询仅支持查询单一分账接收方
     * @date: 2021/10/17 22:11
     * @author: pandans
     */
    public static void doLedgerMposFindBind() {
        MposBind request = new MposBind();
        request.setOrgId(ORGID);
        request.setOrgMerCode(ORGMERCODE);
        request.setOrgTermNo(ORGTERMNO);
        request.setSignType(SIGN_TYPE_RSA);
        //业务产品码
        //request.setProdCode("");

        // 交易流水，28位定长，规则：orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度（唯一）
        request.setOrgTrace(ORGID.substring(0, 4) + ORGID.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));

        MposBind.BizDataBean dataBean = new MposBind.BizDataBean();
        // 分账接收方商户号
        String subOrgMer = ORGLedgerMERCODE;
        dataBean.setOrgMercode(subOrgMer);
        String subOrgTer = ORGLedgerTERMNO;
        dataBean.setOrgTermno(subOrgTer);

        request.setBizData(dataBean);

        // 使用商户私钥对data字段加签
        String sign = sign(dataBean, TEST_MER_RSA_PRIVATE_KEY);
        request.setSign(sign);

        String requestStr = JSON.toJSONString(request);

        try {
            String response = HttpConnectUtils.sendHttpSRequest(BASE_URL_LEDGER + "/ledger/mposfindbind", requestStr, "JSON", null);
            System.out.println("响应报文：" + response);
            checkSign(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * @Description 分账-请求分账， 请求分账接口，将根据分账信息，对原交易订单（交易中已经上送需分账标签）进行分账处理
     * @date: 2021/10/17 21:33
     * @author: pandans
     */
    public static void doLedgerMpos() {
        Mpos request = new Mpos();
        request.setOrgId(ORGID);
        request.setOrgMerCode(ORGMERCODE);
        request.setOrgTermNo(ORGTERMNO);
        request.setSignType(SIGN_TYPE_RSA);

        // 交易流水，28位定长，规则：orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度（唯一）
        request.setOrgTrace(ORGID.substring(0, 4) + ORGID.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));

        Mpos.BizDataBean dataBean = new Mpos.BizDataBean();
        //交易流水号
        dataBean.setOriOrgTrace("ORG0000720220224031331542213");
        //测试随机生成一个key，商户对接时一般整个系统使用一个统一的key
        String aesKey = AesUtil.getKey();
        String dgtl = AesUtil.dgtlEnvelp(aesKey, AesUtil.EASYPAY_PUB_KEY);
        dataBean.setDgtlEnvlp(dgtl);
        dataBean.setTransCount("1");
        dataBean.setTransAmt("1");
        //根据规则生产子订单明细
        List<Mpos.OrderSubBean> orderSubDetailsList = new ArrayList<>(1);
        Mpos.OrderSubBean orderSubBean = new Mpos.OrderSubBean();
        String subOrg = "ORG000000002856";
        String subOrgMer = "531000012972421";
        String subOrgTer = "W1489524";
        orderSubBean.setOrgSubTrace(subOrg.substring(0, 4) + subOrg.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));
        orderSubBean.setOrgMercode(subOrgMer);
        orderSubBean.setOrgTermno(subOrgTer);
        orderSubBean.setTransAmt("1");
        orderSubBean.setFeeCostAmt("1");
        orderSubDetailsList.add(orderSubBean);

        String orderSubDetailsJson = JSON.toJSONString(orderSubDetailsList);
        // 使用aes加密
        String orderSubDetails = AesUtil.encrypt(orderSubDetailsJson, aesKey);
        dataBean.setOrderSubDetails(orderSubDetails);

        request.setBizData(dataBean);
        // 使用商户私钥对data字段加签
        String sign = sign(dataBean, TEST_MER_RSA_PRIVATE_KEY);
        request.setSign(sign);

        String requestStr = JSON.toJSONString(request);

        try {
            String response = HttpConnectUtils.sendHttpSRequest(BASE_URL_LEDGER + "/ledger/mpos", requestStr, "JSON", null);
            System.out.println("响应报文：" + response);
            checkSign(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    /**
     * @Description 分账-分账撤销接口，将根据撤销的原信息，对原分账请求进行撤销，然后可以重新发起分账请求或退款
     * 1、商户请求分账后发现有误可以发起撤销
     * 2、只能撤销当日发起的分账请求
     * 3、原分账请求结算标识为t0的不允许撤销
     * 4、传入需要撤销分账的原分账交易流水号
     * 5、撤销的分账后分账次数会做相应的恢复
     * @date: 2021/10/17 22:04
     * @author: pandans
     */
    public static void doLedgerMposCancel() {
        MposCancel request = new MposCancel();
        request.setOrgId(ORGID);
        request.setOrgMerCode(ORGMERCODE);
        request.setOrgTermNo(ORGTERMNO);
        request.setSignType(SIGN_TYPE_RSA);

        // 交易流水，28位定长，规则：orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度（唯一）
        request.setOrgTrace(ORGID.substring(0, 4) + ORGID.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));

        MposCancel.BizDataBean dataBean = new MposCancel.BizDataBean();
        // 原分账请求交易流水号
        dataBean.setOriOrgTrace("ORG0005320211016071139531569");
        // 原分账请求子订单总笔数
        dataBean.setOriTransAmt("1");
        // 原分账请求子订单总金额
        dataBean.setOriTransCount("1");
        request.setBizData(dataBean);

        // 使用商户私钥对data字段加签
        String sign = sign(dataBean, TEST_MER_RSA_PRIVATE_KEY);
        request.setSign(sign);

        String requestStr = JSON.toJSONString(request);

        try {
            String response = HttpConnectUtils.sendHttpSRequest(BASE_URL_LEDGER + "/ledger/mposcancel", requestStr, "JSON", null);
            System.out.println("响应报文：" + response);
            checkSign(response);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /**
     * @Description 分账-查询商户分账结果
     * 1、请求分账后可调用该接口查询分账结果
     * 2、分账撤销后也可调用该接口查询原请求分账交易是否成功
     * @date: 2021/10/17 22:04
     * @author: pandans
     */
    public static void doLedgerMposFind() {
        MposResult request = new MposResult();
        request.setOrgId(ORGID);
        request.setOrgMerCode(ORGMERCODE);
        request.setOrgTermNo(ORGTERMNO);
        request.setSignType(SIGN_TYPE_RSA);

        // 交易流水，28位定长，规则：orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度（唯一）
        request.setOrgTrace(ORGID.substring(0, 4) + ORGID.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));

        MposResult.BizDataBean dataBean = new MposResult.BizDataBean();
        // 原分账请求交易流水号
        dataBean.setOriOrgTrace("ORG0005320211016071139531569");
        // 原分账请求子订单总笔数
        dataBean.setTransCount("1");
        // 原分账请求子订单总金额
        dataBean.setTransAmt("1");
        request.setBizData(dataBean);

        // 使用商户私钥对data字段加签
        String sign = sign(dataBean, TEST_MER_RSA_PRIVATE_KEY);
        request.setSign(sign);

        String requestStr = JSON.toJSONString(request);

        try {
            String response = HttpConnectUtils.sendHttpSRequest(BASE_URL_LEDGER + "/ledger/mposfind", requestStr, "JSON", null);
            System.out.println("响应报文：" + response);
            checkSign(response);
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    /*******************************=============分账相关结果结束=========================*****************************/



    /*******************************=================退货相关接口==============================************************/
    /**
     * @Description 退货接口，用于合单支付、带有分账标签、无分账标签的原支付订单退货退款，支持部分退款、全额退款。
     * 1、实时退到客户卡中
     * 2、分账标签交易只能退还未分的那部分金额
     * 3、当日交易头寸不得小于退货金额，否则无法退
     * @date: 2021/10/17 22:31
     * @author: pandans
     *
     * 请求示例：
     * {"bizData":{"oriOrgTrace":"ORG0005320211019095744897746","transAmt":"1"},"orgId":"ORG000000000053","orgMerCode":"531000012972310","orgTermNo":"W1489510","orgTrace":"ORG0005320211019103600457841","sign":"VcoUVcEwAU1UA+rKz65AT2fZjOdnrVG4Zuv3KdBQXItRtqobiJW6+hUpNY0pbxxDlmsjjpy7txjOLJTkvZmuQrMWSaEheB/p8spwW9vtqdBjFyEbpsNQjC41g8RihtzsXuaTcSv156KrqFclnuhLVdZ/1dw3RBQHK1VH0PeKl0I=","signType":"RSA"}
     * 返回示例：
     * {"sysRetCode":"000000","sysRetMsg":"[00]success","orgId":"ORG000000000053","orgMerCode":"531000012972310","orgTermNo":"W1489510","prodTrace":"","orgTrace":"ORG0005320211019103600457841","prodCode":"","sign":"ZaSPh1SK9thugi17I96iFn/uBgwZQ+TF5F9TaAbDHkkKxvthdolFbp1kN/LnJBeK7d1qRgVTwFx8LsT8QMDs9srMGUBOyxZG/r5Ar+EaBwq3ZWIevP5y0XRVhPpcPUbGvQqV69xFLvJ415gvtoeYfAn96KV3sY+n4zIsqOfXo6c=","signType":"RSA","bizData":{"tradeRetCode":"00","tradeRetMsg":"[00]success","oriOrgTrace":"ORG0005320211019095744897746","transAmt":"1","pcTrace":"50101609892021101913477519852","outTrace":"1201450288710045290496","stlmDate":"20211019"}}
     */
    private static void doMposRefund() {
        MposRefund request = new MposRefund();
        request.setOrgId(ORGID);
        request.setOrgMerCode(ORGMERCODE);
        request.setOrgTermNo(ORGTERMNO);
        request.setSignType(SIGN_TYPE_RSA);

        // 交易流水，28位定长，规则：orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度（唯一）
        request.setOrgTrace(ORGID.substring(0, 4) + ORGID.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));

        MposRefund.BizDataBean dataBean = new MposRefund.BizDataBean();
        // 原机构交易流水号
        dataBean.setOriOrgTrace("ORG0000720220224022756123456");
        // 原交易日期
        //dataBean.oriBizDate("1");

        dataBean.setTransCount("1");
        // 退货金额
        dataBean.setTransAmt("1");
        request.setBizData(dataBean);

        // 使用商户私钥对data字段加签
        String sign = sign(dataBean, TEST_MER_RSA_PRIVATE_KEY);
        request.setSign(sign);

        String requestStr = JSON.toJSONString(request);




        try {
            String response = HttpConnectUtils.sendHttpSRequest(BASE_URL_LEDGER + "/ledger/mposrefund", requestStr, "JSON", null);
            System.out.println("响应报文：" + response);
            checkSign(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * @Description 退货查询， 1、退货返回异常时，此接口可查询退货的结果
     * @date: 2021/10/18 17:07
     * @author: pandans
     * 请求：{"bizData":{"oriOrgTrace":"ORG0005320211019103600457841","transAmt":"1"},"orgId":"ORG000000000053","orgMerCode":"531000012972310","orgTermNo":"W1489510","orgTrace":"ORG0005320211019103803407491","sign":"LlOND7YXJT5Ki2aXn52wa1zvn3erRHMcQ6leIl7BIfEcLzRKBLACzmq1qdJ81GIS+nsMCuypU/JYaG57yE0iBra8g9jIOWEVzbPuC1JWTXi7bU1sX55deSe71nRKKI8THP1QhuE7T0XzZkAsEBDchzA4Uh+Nbhxt5B04XqwBkaM=","signType":"RSA"}
     * 返回：{"sysRetCode":"000000","sysRetMsg":"[00]success","orgId":"ORG000000000053","orgMerCode":"531000012972310","orgTermNo":"W1489510","prodTrace":"","orgTrace":"ORG0005320211019103803407491","prodCode":"","sign":"RI/t6VyqBVb4GpEtA3SvwZ7ID1NrdUYNsIbmGhl5FUy0GKTY8HDHD6z9mR0IpUJ1JkRk2qaN2+6ZZ1K4KPQJ9tMcR1KUmegs8/vGevXHOKe9tui6dmkEfFQMUe6AdGtZdQTBbBCK7hZ/hYrMXP6BYNno5Wvo5Lxqpz8EsLbZZIY=","signType":"RSA","bizData":{"tradeRetCode":"00","tradeRetMsg":"[00]success","oriOrgTrace":"ORG0005320211019103600457841","transAmt":"1","pcTrace":"50101609892021101913477519852","outTrace":"1201450288710045290496","stlmDate":"20211019"}}
     */
    private static void doMposFindRefund() {
        MposFindRefund request = new MposFindRefund();
        request.setOrgId(ORGID);
        request.setOrgMerCode(ORGMERCODE);
        request.setOrgTermNo(ORGTERMNO);
        request.setSignType(SIGN_TYPE_RSA);

        // 交易流水，28位定长，规则：orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度（唯一）
        request.setOrgTrace(ORGID.substring(0, 4) + ORGID.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));

        MposFindRefund.BizDataBean dataBean = new MposFindRefund.BizDataBean();
        // 原退货请求流水 !!退货请求的orgTrace
        dataBean.setOriOrgTrace("ORG0120620220107155944283395");
        //原交易日期
        //dataBean.setOriBizDate("");
        // 原分账请求子订单总金额
        dataBean.setTransAmt("1");
        request.setBizData(dataBean);

        // 使用商户私钥对data字段加签
        String sign = sign(dataBean, TEST_MER_RSA_PRIVATE_KEY);
        request.setSign(sign);

        String requestStr = JSON.toJSONString(request);

        try {
            String response = HttpConnectUtils.sendHttpSRequest(BASE_URL_LEDGER + "/ledger/mposfindrefund", requestStr, "JSON", null);
            System.out.println("响应报文：" + response);
            checkSign(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * @Description 急速退货-账户代扣
     * 1、实时退到客户卡中
     * 2、虚拟账户中有足够的余额抵扣
     * @date: 2021/10/18 21:55
     * @author: pandans
     */
    private static void doAccRefund() {
        AccRefund request = new AccRefund();
        request.setOrgId(ORGID);
        request.setOrgMerCode(ORGMERCODE);
        request.setOrgTermNo(ORGTERMNO);
        request.setSignType(SIGN_TYPE_RSA);

        // 交易流水，28位定长，规则：orgId 前四位+后四位+yyyyMMddhhmmss+6位自定义 合计28位长度（唯一）
        request.setOrgTrace(ORGID.substring(0, 4) + ORGID.substring(ORGID.length() - 4) + StringUtils.getLocalDate() + RandomUtil.generateNumString(6));

        AccRefund.BizDataBean dataBean = new AccRefund.BizDataBean();
        // 原机构交易流水号
        dataBean.setOriOrgTrace("ORG0005320211016071139531569");
        //原交易日期
//        dataBean.setOriBizDate("");
        // 原分账请求子订单总金额
        dataBean.setTransAmt("1");
        dataBean.setOriBizDate("20211019");
        request.setBizData(dataBean);

        // 使用商户私钥对data字段加签
        String sign = sign(dataBean, TEST_MER_RSA_PRIVATE_KEY);
        request.setSign(sign);

        String requestStr = JSON.toJSONString(request);

        try {
            String response = HttpConnectUtils.sendHttpSRequest(BASE_URL_LEDGER + "/ledger/mposfind", requestStr, "JSON", null);
            System.out.println("响应报文：" + response);
            checkSign(response);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}
